#include <Arduino.h>
#include <Wire.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "OneNETSDK.h"
static WiFiClient espClient;
char DEV_ChipID[16];
#define PRODUCT_KEY "02Z0h14Us9"
#define DEVICE_SECRET ""//onenet密钥
const char *ssid = "styn-iot";
const char *password = "st7713926813";
const char *apiKey = ""; // 聚合数据API密钥
const char *city = "南宁";                               // 要查询的城市
#include <Adafruit_AHTX0.h>                              //AHT20
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/33, /* data=*/32);
Adafruit_AHTX0 AHT;
float Temperature = 0.0; // 温度变量
float Humidity = 0.0;    // 湿度变量
TaskHandle_t CoreTask1;  // 声明CoreTask1任务句柄，用于在核心1上运行任务
TaskHandle_t CoreTask2;  // 声明CoreTask2任务句柄，用于在核心2上运行任务
TaskHandle_t CoreTask3;  // 声明CoreTask3任务句柄，用于在核心2上运行任务
TaskHandle_t CoreTask4;
TaskHandle_t CoreTask5;
TaskHandle_t CoreTask6;
// 窗帘状态
int curtainPosition = 0; // 当前窗帘位置 (0-2400)
int targetPosition = 0;  // 目标位置
int targetPositionon = 0;
int targetPositionoff = 0;
bool consoleinr = false;
bool fsconsole = false;
bool anum = false;
bool bnum = false;
int targetPositionanum = 0;
int targetPositionbnum = 0;
String tq = "晴";

void unlock(JsonVariant console)
{
  int w1_on = console["console"];
  Serial.println(w1_on);
  if (w1_on)
  {
    consoleinr = true;
  }
  else
  {
    consoleinr = false;
  }
  OneNETSDK::loop();
}
void unlock1(JsonVariant targetPositioning)
{
  int w1_on = targetPositioning["targetPosition"];
   Serial.println(w1_on);
  targetPosition = w1_on;
  OneNETSDK::loop();
}
void unlock2(JsonVariant controlfs)
{
  int w1_on = controlfs["controlfs"];
  Serial.println(w1_on);
  if (w1_on)
  {
    digitalWrite(27, HIGH); // 打开LED
  }
  else
  {
    digitalWrite(27, LOW); // 关闭LED
  }
  OneNETSDK::loop();
}
bool containsRain(String weatherStr)
{
  return weatherStr.indexOf("雨") >= 0;
}
void control(bool a, bool b)
{
  if (a)
  {
    digitalWrite(12, HIGH); // 打开LED
  }
  else
  {
    digitalWrite(12, LOW); // 关闭LED
  }
  if (b)
  {
    digitalWrite(14, HIGH); // 打开LED
  }
  else
  {
    digitalWrite(14, LOW); // 关闭LED
  }
}
void controlfs(bool c)
{
  if (c)
  {
    digitalWrite(27, HIGH); // 打开LED
  }
  else
  {
    digitalWrite(27, LOW); // 关闭LED
  }
}
void drawCurtain()
{
  // 计算开合百分比
  int percent = map(curtainPosition, 0, 2400, 0, 100);

  // 绘制窗帘轨道
  u8g2.drawFrame(30, 30, 70, 20);

  // 绘制窗帘
  int curtainWidth = map(percent, 0, 100, 70, 0);
  u8g2.drawBox(30, 30, curtainWidth, 20);

  // 添加褶皱效果
  for (int i = 1; i < 5; i++)
  {
    int foldPos = 30 + (i * curtainWidth / 5);
    u8g2.setDrawColor(0);
    u8g2.drawVLine(foldPos, 30, 20);
    u8g2.setDrawColor(1);
  }

  // 显示百分比
  u8g2.setFont(u8g2_font_5x7_tr);
  u8g2.setCursor(3, 50);
  u8g2.print(percent);
  u8g2.print("%");
}
void updateDisplay(float temp, float humi)
{
  u8g2.clearBuffer();

  // 显示温湿度
  u8g2.setFont(u8g2_font_ncenB10_tr);
  u8g2.setCursor(2, 12);
  u8g2.print(" T:");
  u8g2.print(temp, 1);
  u8g2.print(" C");
  u8g2.setCursor(2, 26);
  u8g2.print(" H:");
  u8g2.print(humi, 1);
  u8g2.print(" %");

  // 绘制窗帘
  drawCurtain();

  u8g2.sendBuffer();
}

void updateCurtainDisplay()
{
  // 只更新窗帘部分区域以提高刷新效率
  u8g2.setDrawColor(0);
  u8g2.drawBox(0, 30, 128, 34);
  u8g2.setDrawColor(1);

  drawCurtain();
  u8g2.sendBuffer();
}

void task1(void *pvParameters)
{
  // Wire.begin(32, 33);
  AHT.begin();
  sensors_event_t humidity, temp;
  while (1)
  {
    AHT.getEvent(&humidity, &temp);
    // 更新温度和湿度数据
    Temperature = temp.temperature - 0.86;
    Humidity = humidity.relative_humidity;
    vTaskDelay(100);
  }
}
void task2(void *pvParameters)
{
  // 初始化OLED
  // Wire.begin(32, 33);
  u8g2.begin();
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.drawStr(20, 30, "系统初始化中...");
  u8g2.sendBuffer();
  while (1)
  {
    updateDisplay(Temperature, Humidity);
    // 平滑移动窗帘
    if (curtainPosition < targetPosition)
    {
      curtainPosition += 20;

      if (curtainPosition > targetPosition)
        curtainPosition = targetPosition;
      updateDisplay(Temperature, Humidity);
    }
    else if (curtainPosition > targetPosition)
    {
      curtainPosition -= 20;

      if (curtainPosition < targetPosition)
        curtainPosition = targetPosition;
      updateDisplay(Temperature, Humidity);
    }

    vTaskDelay(100);
  }
}
void task3(void *pvParameters)
{
  Serial.begin(115200); // 初始化串口
  while (1)
  {
    if (consoleinr)
    {
      /* code */
    }
    else
    {
      if (containsRain(tq))
      {
        controlfs(true);
        targetPosition = 0;
      }
      else
      {
            if (Humidity >= 95)
    {
      controlfs(true);
    }
    else
    {
      controlfs(false);
    }
        if (Temperature >= 24.0 && Temperature < 27.0)
        {
          targetPosition = 800;
        }
        else if (Temperature >= 27.0 && Temperature < 30.0)
        {
          targetPosition = 1200;
        }
        else if (Temperature >= 30.0 && Temperature <= 35.0)
        {
          targetPosition = 1800;
        }
        else if (Temperature >= 35.0)
        {
          targetPosition = 2200;
        }
      }
    }
    vTaskDelay(2000);
  }
}
void task4(void *pvParameters)
{
  Serial.begin(115200); // 初始化串口
  HTTPClient http;
  // 构建请求URL
  String url = "http://apis.juhe.cn/simpleWeather/query?city=" + String(city) + "&key=" + String(apiKey);

  http.begin(url); // 发起HTTP请求
  DynamicJsonDocument doc(2048);
  while (1)
  {

    int httpCode = http.GET();

    if (httpCode == HTTP_CODE_OK)
    {
      String payload = http.getString();
      deserializeJson(doc, payload);

      if (doc["error_code"] != 0)
      {
        Serial.println("获取天气数据失败: " + String(doc["reason"].as<const char *>()));
        return;
      }
      // 解析实时天气
      JsonObject realtime = doc["result"]["realtime"];
      String weather = realtime["info"]; // 天气现象
      tq = weather;
    }
    else
    {
      Serial.printf("HTTP请求失败，错误码: %d\n", httpCode);
    }

    http.end();
    vTaskDelay(300000);
  }
}

void task5(void *pvParameters)
{
  while (1)
  {
    if (curtainPosition < targetPosition)
    {

      control(true, false);
    }
    else
    {

      control(false, true);
    }
    if (curtainPosition == targetPosition)
    {

      control(false, false);
    }
    vTaskDelay(100);
  }
}
void task6(void *pvParameters)
{
  while (1)
  {
    OneNETSDK::send("Temperature", Temperature);
    OneNETSDK::send("Humidity", Humidity);
    OneNETSDK::loop();
    vTaskDelay(30000);
  }
}
void setup()
{
  Wire.begin(32, 33);
  Wire.setClock(400000); // 100kHz
  Serial.begin(115200);  // 初始化串口
  pinMode(27, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(12, OUTPUT);
  WiFi.begin(ssid, password);
  uint32_t chipId = 0;
  for (int i = 0; i < 17; i = i + 8)
  {
    chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
  }
  snprintf(DEV_ChipID, 16, "ELE-%06X", chipId);

  OneNETSDK::begin(espClient, PRODUCT_KEY, DEV_ChipID, DEVICE_SECRET);
  vTaskDelay(5000);
  OneNETSDK::bindData("console", unlock);
  OneNETSDK::bindData("targetPosition", unlock1);
  OneNETSDK::bindData("controlfs", unlock2);
  xTaskCreatePinnedToCore(
      task1,      // 实现任务的函数名称
      "HQQX",     // 任务的任何名称，按实际功能起名
      16384,      // 分配给任务的堆栈大小，以字节为单位，先尝试一下分配16K够不够
      NULL,       // 任务输入参数，可以为NULL
      1,          // 任务优先级，3最高，0最低
      &CoreTask1, // 任务句柄，头部已定义，亦可以为NULL
      0);         // 任务运行的内核ID（0或者1）
  xTaskCreatePinnedToCore(
      task2,      // 实现任务的函数名称
      "SEND",     // 任务的任何名称，按实际功能起名
      16384,      // 分配给任务的堆栈大小，以字节为单位，先尝试一下分配64K够不够
      NULL,       // 任务输入参数，可以为NULL
      0,          // 任务优先级，3最高，0最低
      &CoreTask2, // 任务句柄，头部已定义，亦可以为NULL
      0);         // 任务运行的内核ID（0或者1）
  xTaskCreatePinnedToCore(
      task3,      // 实现任务的函数名称
      "BDHQ",     // 任务的任何名称，按实际功能起名
      16384,      // 分配给任务的堆栈大小，以字节为单位，先尝试一下分配16K够不够
      NULL,       // 任务输入参数，可以为NULL
      0,          // 任务优先级，3最高，0最低
      &CoreTask3, // 任务句柄，头部已定义，亦可以为NULL
      0);         // 任务运行的内核ID（0或者1）
                  // xTaskCreatePinnedToCore(
                  //     task4,      // 实现任务的函数名称
                  //     "BDHQ",     // 任务的任何名称，按实际功能起名
                  //     16384,      // 分配给任务的堆栈大小，以字节为单位，先尝试一下分配16K够不够
                  //     NULL,       // 任务输入参数，可以为NULL
                  //     1,          // 任务优先级，3最高，0最低
                  //     &CoreTask4, // 任务句柄，头部已定义，亦可以为NULL
                  //     0);         // 任务运行的内核ID（0或者1）
  xTaskCreatePinnedToCore(
      task5,      // 实现任务的函数名称
      "BDHQ",     // 任务的任何名称，按实际功能起名
      16384,      // 分配给任务的堆栈大小，以字节为单位，先尝试一下分配16K够不够
      NULL,       // 任务输入参数，可以为NULL
      0,          // 任务优先级，3最高，0最低
      &CoreTask5, // 任务句柄，头部已定义，亦可以为NULL
      0);         // 任务运行的内核ID（0或者1）
  xTaskCreatePinnedToCore(
      task6,      // 实现任务的函数名称
      "BDHQ",     // 任务的任何名称，按实际功能起名
      16384,      // 分配给任务的堆栈大小，以字节为单位，先尝试一下分配16K够不够
      NULL,       // 任务输入参数，可以为NULL
      1,          // 任务优先级，3最高，0最低
      &CoreTask6, // 任务句柄，头部已定义，亦可以为NULL
      1);         // 任务运行的内核ID（0或者1）
  OneNETSDK::loop();
}
void loop()
{
  OneNETSDK::loop();
  vTaskDelay(10);
}
